#!/usr/bin/php
<?php

include "query.lib.php";

$args = parseArgs($_SERVER['argv']);
$id=1;

if(preg_match("/http.*/",$args['wsdl']))
	$client = new pncSoapClient($args['wsdl']);
else $client = new pncSshClient($args['wsdl']);
$hello=$client->hello();
if($args["interactive"]) {
	ihelp();
	while(true) {
		$query=readline("> ");
		if(preg_match("/^(\d+)\s?(.*)/",$query,$m))
			predefined($m[1],$m[2]);
		elseif($query=="h")
			ihelp();
		elseif(preg_match("/q (\S*) (\S*) (\S*) (\S*) (\S*) (\S*) (\S*) (\S*) (\S*)/",$query,$m))
			print insertquery($m[1],$m[2],$m[3],$m[4],$m[5],$m[6],$m[7],$m[8],$m[9]);
		else
			xpathquery($query);
	}
} elseif($args["getdata"])
		getReport($args);
elseif(isset($args["query"]))
	print xmlpp($client->get($args["query"])->saveXML());		

function getReport($args) {
	global $client,$cfg;
	$name="query".rand();
	if(!$args['obspoints'])
		$args['obspoints']=getFirstObspoint($args["ma"],$args["datasource"]);
	if($args['from'])
		$args['timeperiods']=getTimeperiods($args["ma"],$args["datasource"],$args['from'],$args['to'],$args['duration']);
	if(!$args['timeperiods'])
		$args['timeperiods'][]=getLastTimeperiod($args["ma"],$args["datasource"]);	
	insertquery($name,$args['ma'],$args['datasource'],$args['report'],$args['type'],$args['view'],$args['duration'],$args['timeperiods'],$args['obspoints'],$args['limit'],$args['arguments'],$args['sort']);
	if($args['query']) {		
		$xml=$client->get($args["query"])->saveXML();
		print xmlpp($xml);
	}
	else {
		$data=$client->get("/nc:data/pn:perfSONARNC/pn:measurementArchivesAndQueries/pn:queries/pn:query[pn:name='$name' and pn:ma='".$args['ma']."' and pn:dataSource='".$args['datasource']."']");
		print_r($cfg);
		if($args['print'])	
			printQuery($args['ma'],$args['datasource'],$data,true,$args['header']);
	}
}

function getTimeperiods($ma,$source,$from,$to,$secs=null) {
	global $client;    
	if(!$secs) {
		$tmp=$client->get("/nc:data/pn:perfSONARNC/pn:measurementArchivesAndQueries/pn:mas/pn:ma[pn:id=$ma]/pn:dataSources/pn:dataSource[pn:id='$source']/pn:timeInfo/pn:resolution[1]/pn:duration");
		$secs=$tmp->getElementsByTagNameNS("http://stager.uninett.no/perfsonarnc/1.0",'duration')->item(0)->textContent;
	}
	if(!$to) {
	  $last=getLastTimeperiod($ma,$source);
	  $to=$last['timestamp'];
	} else
	  $to=strtotime($to);
	$from=strtotime($from);
	$ret=array();
	for($t=$from;$t<=$to;$t+=$secs)
	  $ret[]=array('duration'=>$secs,'timestamp'=>$t);
	return $ret;
}

function getFirstObspoint($ma,$source) {
	global $client;
	$res=$client->get("/nc:data/pn:perfSONARNC/pn:measurementArchivesAndQueries/pn:mas/pn:ma[pn:id='".$ma."']/pn:dataSources/pn:dataSource[pn:id='".$source."']/pn:obsPoints/pn:obsPoint[1]/pn:id");
	return $res->getElementsByTagNameNS("http://stager.uninett.no/perfsonarnc/1.0",'id')->item(0)->textContent;
}

function getDuration($ma,$source) {
	global $client;
	$tmp=$client->get("/nc:data/pn:perfSONARNC/pn:measurementArchivesAndQueries/pn:mas/pn:ma[pn:id=$ma]/pn:dataSources/pn:dataSource[pn:id='$source']/pn:timeInfo/pn:resolution[1]/pn:duration");
	return $tmp->getElementsByTagNameNS("http://stager.uninett.no/perfsonarnc/1.0",'duration')->item(0)->textContent;	
}

function getLastTimeperiod($ma,$source) {
	global $client;
	$tmp=$client->get("/nc:data/pn:perfSONARNC/pn:measurementArchivesAndQueries/pn:mas/pn:ma[pn:id=$ma]/pn:dataSources/pn:dataSource[pn:id='$source']/pn:timeInfo/pn:resolution[1]/pn:duration");
	$secs=$tmp->getElementsByTagNameNS("http://stager.uninett.no/perfsonarnc/1.0",'duration')->item(0)->textContent;
	$res=$client->get("/nc:data/pn:perfSONARNC/pn:measurementArchivesAndQueries/pn:mas/pn:ma[pn:id='".$ma."']/pn:dataSources/pn:dataSource[pn:id='".$source."']/pn:timeInfo/pn:resolution[pn:duration=$secs]/pn:last");
	return array('duration'=>$secs,'timestamp'=>$res->getElementsByTagNameNS("http://stager.uninett.no/perfsonarnc/1.0",'last')->item(0)->textContent);	
}

function parseArguments($ma,$ds,$rep,$arguments) {
	global $client;
	$args=$client->get("/nc:data/pn:perfSONARNC/pn:measurementArchivesAndQueries/pn:mas/pn:ma[pn:id=$ma]/pn:dataSources/pn:dataSource[pn:id='$ds']/pn:reportsInfo/pn:reportInfo[pn:id='$rep']/pn:arguments/pn:argument");
	$ret="";
	if($args->getElementsByTagNameNS("http://stager.uninett.no/perfsonarnc/1.0",'argument')->length>0) {
		foreach($args->getElementsByTagNameNS("http://stager.uninett.no/perfsonarnc/1.0",'argument') as $arg) {
			$id=$arg->getElementsByTagNameNS("http://stager.uninett.no/perfsonarnc/1.0",'id')->item(0)->textContent;
			$name=$arg->getElementsByTagNameNS("http://stager.uninett.no/perfsonarnc/1.0",'name')->item(0)->textContent;
			$descr=$arg->getElementsByTagNameNS("http://stager.uninett.no/perfsonarnc/1.0",'descr')->item(0)->textContent;
			$tmp=$arg->getElementsByTagNameNS("http://stager.uninett.no/perfsonarnc/1.0",'default')->item(0);
			$enums=$arg->getElementsByTagNameNS("http://stager.uninett.no/perfsonarnc/1.0",'enumeration')->item(0);
			if($tmp)
			$default=$tmp->textContent;
			else
				$default="";
			if(isset($arguments[$id]))
				$value=$arguments[$id];
			else {
				print "Name: $name\nDescr: $descr";
				if($enums) {
					print "\nPossible values: ";
					$nodes=$enums->getElementsByTagNameNS("http://stager.uninett.no/perfsonarnc/1.0",'enum');
					foreach($nodes as $n)
					print $n->textContent.",";
				}
				$value=readline("\nValue ($default): ");

				if($value=="")
				$value=$default;
				print "\n";
			}
			if($value!="")
			$ret.="<argument><id>$id</id><value>$value</value></argument>";
		}
		return "<arguments>$ret</arguments>";
	}
	return "";
}

function insertquery($name,$ma,$source,$rep,$type,$view,$duration,$timeperiod,$obs,$limit=null,$arguments=null,$sort=null) {
	global $client;
	if(!$duration)
		$duration=getDuration($ma,$source);
	$filter=parseArguments($ma,$source,$rep,$arguments);
	$xmlstr="<perfSONARNC xmlns='http://stager.uninett.no/perfsonarnc/1.0'>
	<measurementArchivesAndQueries>
	<queries>
	<query>
	<name>$name</name>
	 <ma>$ma</ma>
	  <dataSource>$source</dataSource>	    		
		<report>$rep</report>
		<type>$type</type>
		<view>$view</view>
		<obsPoints>".parseString($obs,"obsPoint")."</obsPoints>
		<timePeriods>".parseTimeperiods($duration,$timeperiod)."</timePeriods>
		<limit>$limit</limit>
		<sort>$sort</sort>
		$filter
	      </query>
	    </queries>
      </measurementArchivesAndQueries>
            </perfSONARNC>
      ";
	$dom=new domdocument();
	$dom->loadXML($xmlstr);
	$res=$client->editconfig($dom);
	return xmlpp($res->saveXML())."\n";
}

function parseTimeperiods($duration,$timeperiods) {
  $str="";
  foreach($timeperiods as $tp)
    $str.="<timePeriod><resolution>$duration</resolution><timestamp>".$tp['timestamp']."</timestamp></timePeriod>";
  return $str;
}

function parseString($str,$tag) { 
	if($str=="all")
		return "<all/>";
	if(preg_match("/query:(.*)/",$str,$m))
		return "<query>".$m[1]."</query>";
	$nodes=explode(",",$str);
	sort($nodes);
	$str="";
	foreach($nodes as $n)
		$str.="<$tag>$n</$tag>";
	return $str;
}

function predefined($id,$argstr) {
	global $client;
	switch($id) {
		case 1: 
			xpathquery("/nc:data/pn:perfSONARNC/pn:measurementArchivesAndQueries/pn:mas/pn:ma/pn:id|//pn:measurementArchivesAndQueries/pn:mas/pn:ma/pn:name");
			break;
		case 2:
			xpathquery("/nc:data/pn:perfSONARNC/pn:measurementArchivesAndQueries/pn:mas/pn:ma[pn:id=$argstr]/pn:dataSources/pn:dataSource/pn:id|//pn:ma[pn:id=$argstr]/pn:dataSources/pn:dataSource/pn:name");
			break;
		case 3:
			list($ma,$source)=explode(" ",$argstr);
			xpathquery("/nc:data/pn:perfSONARNC/pn:measurementArchivesAndQueries/pn:mas/pn:ma[pn:id=$ma]/pn:dataSources/pn:dataSource[pn:id='$source']/pn:obsPoints/pn:obsPoint");
			break;
		case 4:
			list($ma,$source)=explode(" ",$argstr);
			xpathquery("/nc:data/pn:perfSONARNC/pn:measurementArchivesAndQueries/pn:mas/pn:ma[pn:id=$ma]/pn:dataSources/pn:dataSource[pn:id='$source']/pn:timeResolutionsInfo/pn:timeResolutionInfo");
			break;
		case 5:
			list($ma,$source,$secs)=explode(" ",$argstr);
			xpathquery("/nc:data/pn:perfSONARNC/pn:measurementArchivesAndQueries/pn:mas/pn:ma[pn:id=$ma]/pn:dataSources/pn:dataSource[pn:id='$source']/pn:timePeriods/pn:resolution[pn:duration=$secs]/pn:timeperiod[last()]");
			break;
		case 6:
			list($ma,$source)=explode(" ",$argstr);
			$reports=$client->get("/nc:data/pn:perfSONARNC/pn:measurementArchivesAndQueries/pn:mas/pn:ma[pn:id=$ma]/pn:dataSources/pn:dataSource[pn:id='$source']/pn:reportsInfo/pn:reportInfo/pn:id");
			foreach($reports->getElementsByTagNameNS("http://stager.uninett.no/perfsonarnc/1.0",'id') as $id) {
				print $id->textContent."\n";
				$types=$client->get("/nc:data/pn:perfSONARNC/pn:measurementArchivesAndQueries/pn:mas/pn:ma[pn:id=$ma]/pn:dataSources/pn:dataSource[pn:id='$source']/pn:reportsInfo/pn:reportInfo[pn:id='".$id->textContent."']/pn:reportTypes/pn:reportType/pn:type");
				foreach($types->getElementsByTagNameNS("http://stager.uninett.no/perfsonarnc/1.0",'type') as $type) {
					print "\t".$type->textContent."\n";
					$views=$client->get("/nc:data/pn:perfSONARNC/pn:measurementArchivesAndQueries/pn:mas/pn:ma[pn:id=$ma]/pn:dataSources/pn:dataSource[pn:id='$source']/pn:reportsInfo/pn:reportInfo[pn:id='".$id->textContent."']/pn:reportTypes/pn:reportType[pn:type='".$type->textContent."']/pn:views/pn:view/pn:id");
					foreach($views->getElementsByTagNameNS("http://stager.uninett.no/perfsonarnc/1.0",'id') as $view)
						print "\t\t".$view->textContent."\n";
				}
			}
			break;
		case 7:
			list($ma,$source,$queryname)=explode(" ",$argstr);
			$query=$client->get("/nc:data/pn:perfSONARNC/pn:measurementArchivesAndQueries/pn:queries/pn:query[pn:name='$queryname' and pn:ma='$ma' and pn:dataSource='$source']");		
			printQuery($ma,$source,$query);
			break;			
	}
}

function xpathquery($query) {
	global $client;
	$res=$client->get($query);
	print xmlpp($res->saveXML())."\n";
}

function ihelp() {
	//print interactive help
	print "Predefined queries:\n\t<query #> <arguments>\n";
	print "\t\t1 - list measurement archives\n";
	print "\t\t2 <ma#> - list data sources\n";
	print "\t\t3 <ma#> <datasource> - show available obspoints\n";
	print "\t\t4 <ma#> <datasource> - show information about available time resolutions\n";
	print "\t\t5 <ma#> <datasource> <duration> - list last available timeperiod with a duration of <duration> seconds\n";
	print "\t\t6 <ma#> <datasource> - show information about available reports, report types and views\n";
	print "\t\t7 <ma#> <datasource> <query name> - show results of query\n";
	print "Register new report query:\n";
	print "\tq <query name> <ma#> <datasource> <report> <type> <view> <timeperiod1,timeperiod2,....> <obspoint1,obspoint2,....> <limit>\n";
	print "XPATH query:\n\t<xpath query> (use pn: as namespace)\n";
}

function parseArgs($args) {

	$usage = "Usage: maquery.php <options> <host>\n" .
    "Options:\n" .
	"\t-q <xpath query>\n".
	"\t-i interactive mode\n".
	"\t-r <ma> <datasource> <report> <type> <view>\n".
	"\t-f <yyyy-mm-dd hh:mm> from timestamp\n".
	"\t-t <yyyy-mm-dd hh:mm> to timestamp\n".
	"\t-n no printing of report data\n".
	"\t-o <obspointid1>,<obspointid2>....\n".
    "\t-v verbose\n";

	$ret = array ();
	$ret['debug']=0;
	$ret['interactive']=false;
	$ret['getdata']=false;
	$ret['obspoints']=false;
	$ret['timeperiods']=false;
	$ret['from']=false;
	$ret['to']=false;
	$ret['header']=false;
	$ret['arguments']=array();
	$ret['sort']=null;
	$ret['limit']=null;
	$ret['query']=false;
	$ret['duration']=false;
	$ret['print']=true;

	for ($i = 1; $i < count($args); $i++) {
		switch ($args[$i]) {
			case '-q' :
				$ret['query'] = $args[++$i];
				break;
			case '-i' :
				$ret['interactive'] = true;
				break;
			case '-n' :
				$ret['print'] = false;
				break;				
			case '-f' :
				$ret['from'] = $args[++$i];
				break;
			case '-t' :
				$ret['to'] = $args[++$i];
				break;
			case '-l' :
				$ret['limit'] = $args[++$i];
				break;				
			case '-s' :
				$ret['sort'] = $args[++$i];
				break;
			case '-d' :
				$ret['duration'] = $args[++$i];
				break;												
			case '-v' :
				$ret['debug']++;
				break;			
			case '-a' :
				$ret['arguments'][$args[++$i]]=$args[++$i];
				break;
			case '-o' :
				$ret['obspoints'] = $args[++$i];
				break;
			case '-r' :
				$ret['getdata']=true;
				$ret['ma']=$args[++$i];
				$ret['datasource']=$args[++$i];
				$ret['report']=$args[++$i];
				$ret['type']=$args[++$i];
				$ret['view']=$args[++$i];
				break;
			case '-p' :
				$ret['header']=true;
				break;
			case '-h' :
				die($usage);
			default :
				$ret['wsdl'] = $args[$i];
		}
	}

	if (!isset ($ret['wsdl']) or !(isset($ret['interactive']) or isset($ret['query']) or isset($ret['custom'])))
	die($usage);
	return $ret;
}


?>